home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_10 / mashlan / checkptr.h < prev    next >
C/C++ Source or Header  |  1995-04-15  |  8KB  |  279 lines

  1. // checkptr.h listing 1
  2. // copyright 1995 Robert Mashlan
  3. // class templates for CheckedPtr and CheckedClassPtr
  4.  
  5. #ifndef __CHECKPTR_H
  6. #define __CHECKPTR_H
  7.  
  8. #include <stddef.h>
  9. #include <except.h>
  10. #include <cstring.h>
  11.  
  12. class xCheckedPtr : public xmsg
  13. {
  14.    public:
  15.       xCheckedPtr( const string& why ) : xmsg(why) {}
  16. };
  17.  
  18. class xnullptr : public xCheckedPtr {
  19.    public:
  20.       xnullptr() : xCheckedPtr("dereferenced null pointer") {}
  21.       void raise()
  22.          { throw *this; }
  23. };
  24.  
  25. class xoutofrange : public xCheckedPtr {
  26.    public:
  27.       xoutofrange() : xCheckedPtr("pointer out of range") {}
  28.       void raise()
  29.          { throw *this; }
  30. };
  31.  
  32. class xnotsamebase : public xCheckedPtr {
  33.    public:
  34.       xnotsamebase()
  35.          : xCheckedPtr("comparison between two pointers not of the same base")
  36.          {}
  37.       void raise()
  38.          { throw *this; }
  39. };
  40.  
  41. template<class T>
  42. class CheckedPtr {
  43.    public:
  44.       // default constructor
  45.       CheckedPtr(T *p = 0, size_t limit=1, T* base = 0 )
  46.          : p(p), base(base?base:p), limit(limit)
  47.          {
  48.             if(p>this->base+limit||p<this->base)
  49.                xoutofrange().raise();
  50.          }
  51.       // copy constructor
  52.       CheckedPtr( const CheckedPtr<T>& orig )
  53.          : p(orig.p), base(orig.base), limit(orig.limit)
  54.          {}
  55.  
  56.       // access to base and limit
  57.       void SetBaseAndLimit( T* base, size_t limit )
  58.          {
  59.             if(!base)
  60.                base = p;
  61.             if(!limit)
  62.                limit = 1;
  63.             this->base=base;
  64.             this->limit=limit;
  65.             if( p && (p<base || base+limit<p) )
  66.                xoutofrange().raise();
  67.          }
  68.  
  69.       // conversion operator
  70.       operator T*() const
  71.          { return p; }
  72.  
  73.       // reference operators
  74.       T& operator*() const
  75.          { return operator[](0); }
  76.       T& operator[]( ptrdiff_t i ) const
  77.          {
  78.             if(!p) // null pointer?
  79.               xnullptr().raise();
  80.             // check for out of range reference
  81.             if( p+i<base || base+limit <= p+i )
  82.               xoutofrange().raise();
  83.             return p[i];
  84.          }
  85.       // assignment operators
  86.       CheckedPtr<T>& operator=( const CheckedPtr<T>& cp )
  87.          { p = cp.p; base=cp.base; limit=cp.limit; return *this; }
  88.       CheckedPtr<T>& operator=( T* p )
  89.          { this->p = base = p; limit = 1; return *this; }
  90.       CheckedPtr<T>& operator+=( ptrdiff_t n )
  91.          {
  92.             if(!p)
  93.                xnullptr().raise();
  94.             if( p+n < base || base + limit < p+n )
  95.                xoutofrange().raise();
  96.             p += n;
  97.             return *this;
  98.          }
  99.       CheckedPtr<T>& operator-=( ptrdiff_t n )
  100.          { return operator+=(-n); }
  101.       // additive operators
  102.       CheckedPtr<T> operator+( ptrdiff_t n ) const
  103.          { return CheckedPtr<T>(*this).operator+=(n); }
  104.       CheckedPtr<T> operator-( ptrdiff_t n ) const
  105.          { return CheckedPtr<T>(*this).operator-=(n); }
  106.       ptrdiff_t operator-( const CheckedPtr<T>& cp ) const
  107.          {
  108.             if(base!=cp.base)
  109.                xnotsamebase().raise();
  110.             return p-cp.p;
  111.          }
  112.       ptrdiff_t operator-( CheckedPtr<T>& cp ) const
  113.          { return operator-((const CheckedPtr<T>)cp); }
  114.       ptrdiff_t operator-( T *p ) const
  115.          {
  116.             if( p<base || base+limit<p )
  117.                xnotsamebase().raise();
  118.             return this->p-p;
  119.          }
  120.       friend ptrdiff_t operator-( T* p, CheckedPtr<T>& cp );
  121.  
  122.       // increment and decrement
  123.       CheckedPtr<T>& operator++(int)
  124.          { return operator+=(1); }
  125.       CheckedPtr<T> operator++()
  126.          {
  127.             CheckedPtr<T> r(*this);
  128.             operator++(0);
  129.             return r;
  130.          }
  131.       CheckedPtr<T>& operator--(int)
  132.          { return operator-=(1); }
  133.       CheckedPtr<T> operator--()
  134.          {
  135.             CheckedPtr<T> r(*this);
  136.             operator--(0);
  137.             return r;
  138.          }
  139.  
  140.       // logical negation
  141.       bool operator!() const
  142.          { return !p; }
  143.  
  144.       // equality operators
  145.       bool operator==( const CheckedPtr<T>& cp ) const
  146.          { return p == cp.p; }
  147.       bool operator==( T* p ) const
  148.          { return this->p == p; }
  149.       bool operator != ( const CheckedPtr<T>& cp ) const
  150.          { return p != cp.p; }
  151.       bool operator!=( T* p ) const
  152.          { return this->p != p; }
  153.  
  154.       // relational operators
  155.       bool operator<( const CheckedPtr<T>& cp ) const
  156.          { return operator-(cp) < 0; }
  157.       bool operator<( T* p ) const
  158.          { return operator-(p) < 0; }
  159.       bool operator<=( const CheckedPtr<T>& cp ) const
  160.          { return operator-(cp) <= 0; }
  161.       bool operator<=( T* p ) const
  162.          { return operator-(p) <= 0; }
  163.       bool operator>( const CheckedPtr<T>& cp ) const
  164.          { return operator-(cp) > 0; }
  165.       bool operator>( T* p ) const
  166.          { return operator-(p) > 0; }
  167.       bool operator>=( const CheckedPtr<T>& cp ) const
  168.          { return operator-(cp) >= 0; }
  169.       bool operator>=( T* p ) const
  170.          { return operator-(p) >= 0; }
  171.  
  172.    protected:
  173.       T* p;         // pointer that this class represents
  174.       T* base;      // base of the array that p is a member of
  175.       size_t limit; // number of elements in the array,
  176.                     // 1 for non-array pointers
  177. };
  178.  
  179. template<class T> inline
  180. ptrdiff_t operator-( T* p, CheckedPtr<T>& cp )
  181. {
  182.    if( p < cp.base || cp.base+cp.limit < p )
  183.       xnotsamebase().raise();
  184.    return p-cp.p;
  185. }
  186.  
  187. template<class T> inline
  188. CheckedPtr<T> operator+( ptrdiff_t n, const CheckedPtr<T>& cp )
  189. {
  190.    return cp.operator+(n);
  191. }
  192.  
  193. // non-member equality operators
  194.  
  195. template<class T> inline
  196. bool operator==( T* p, const CheckedPtr<T>& cp )
  197. {
  198.    return cp.operator==(p);
  199. }
  200.  
  201. template<class T> inline
  202. bool operator!=( T* p, const CheckedPtr<T>& cp )
  203. {
  204.    return cp.operator!=(p);
  205. }
  206.  
  207.  
  208. // non-member relational operators
  209.  
  210. template<class T> inline
  211. bool operator<( T* p, const CheckedPtr<T>& cp )
  212. {
  213.    return cp.operator>=(p);
  214. }
  215.  
  216. template<class T> inline
  217. bool operator<=( T* p, const CheckedPtr<T>& cp )
  218. {
  219.    return cp.operator>(p);
  220. }
  221.  
  222. template<class T> inline
  223. bool operator>( T* p, const CheckedPtr<T>& cp )
  224. {
  225.    return cp.operator<=(p);
  226. }
  227.  
  228. template<class T> inline
  229. bool operator>=( T* p, const CheckedPtr<T>& cp )
  230. {
  231.    return cp.operator<(p);
  232. }
  233.  
  234. template<class T>
  235. class CheckedClassPtr : public CheckedPtr<T> {
  236.    public:
  237.       CheckedClassPtr(T *p=0, size_t limit=1, T* base=0 )
  238.          : CheckedPtr<T>(p,limit,base)
  239.          {}
  240.       CheckedClassPtr( const CheckedClassPtr<T>& orig )
  241.          : CheckedPtr<T>(orig)
  242.          {}
  243.  
  244.       // class memory access operator
  245.       T* operator->() const { return &operator*(); }
  246.  
  247.       // assignment operators
  248.       CheckedClassPtr<T>& operator=( const CheckedClassPtr<T>& cp )
  249.          { CheckedPtr<T>::operator=(cp); return *this; }
  250.       CheckedClassPtr<T>& operator+=( ptrdiff_t n )
  251.          { CheckedPtr<T>::operator+=(n); return *this; }
  252.       CheckedClassPtr<T>& operator-=( ptrdiff_t n )
  253.          { CheckedPtr<T>::operator-=(n); return *this; }
  254.  
  255.       // additive operators
  256.       CheckedClassPtr<T> operator+( ptrdiff_t n ) const
  257.          { return CheckedClassPtr<T>(*this).operator+=(n); }
  258.       CheckedClassPtr<T> operator-( ptrdiff_t n ) const
  259.          { return CheckedClassPtr<T>(*this).operator-=(n); }
  260.  
  261.       // increment and decrement
  262.       CheckedClassPtr<T>& operator++(int)
  263.          { return operator+=(1); }
  264.       CheckedClassPtr<T> operator++()
  265.          { CheckedClassPtr<T> r(*this); operator++(0); return r; }
  266.       CheckedClassPtr<T>& operator--(int)
  267.          { operator-=(1); return *this; }
  268.       CheckedClassPtr<T> operator--()
  269.          { CheckedClassPtr<T> r(*this); operator--(0); return r; }
  270. };
  271.  
  272. template<class T> inline
  273. CheckedClassPtr<T> operator + ( ptrdiff_t n, const CheckedClassPtr<T>& p )
  274. {
  275.    return p.operator+(n);
  276. }
  277.  
  278. #endif
  279.